package com.zhenyi.core.interceptor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import com.cjw.model.DBMap;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
import com.wxpay.utils.MD5Util;

public class SignInterceptor implements Interceptor {

	private void renderAuth(Controller controller) {
		DBMap map = new DBMap();
		map.put("status", 401);
		map.put("msg", "sign error");
		LogKit.warn(controller.getRequest().getQueryString());
		controller.renderJson(map);
		// controller.renderError(401);
	}

	private final Cache cache = Redis.use();
	/**
	 * 同一个签名只能用一次
	 */
	private final Integer SIGN_INTERVAL = singInterval();

	/**
	 * 签名有效市场
	 * 
	 * @return
	 */
	protected Integer singInterval() {
		return 120;
	}

	/**
	 * 签名标识
	 * 
	 * @return
	 */
	protected String cacheKey() {
		return "ZhenyiTechCache";
	}

	/**
	 * 自定义验证
	 * 
	 * @param params
	 * @return
	 */
	protected boolean onVerify(Map<String, String> params) {
		return true;
	}

	@Override
	public void intercept(Invocation inv) {
		Controller controller = inv.getController();
		try {
			Long timestamp = controller.getParaToLong("timestamp");
			String sign = controller.getPara("sign");
			// String token = controller.getPara("token");
			// if (StrKit.isBlank(token)) {
			// renderAuth(controller);
			// return;
			// }
			if (PropKit.getBoolean("devMode", false)) {
				inv.invoke();
				return;
			}
			if (StrKit.isBlank(sign)) {
				LogKit.warn("sign blank");
				renderAuth(controller);
				return;
			}
			String cacheKey = cacheKey() + sign;
			if (cache.get(cacheKey) != null) {
				LogKit.warn("cache used");
				renderAuth(controller);
				return;
			}
			if (timestamp == null) {
				LogKit.warn("timestamp null");
				renderAuth(controller);
				return;
			}
			Long time = System.currentTimeMillis() / 1000;
			Long gap = Math.abs(timestamp - time);
			if (gap > 120) {
				LogKit.warn("gap >120");
				renderAuth(controller);
				return;
			}
			Map<String, String> params = new HashMap<String, String>();
			ArrayList<String> aList = Collections.list(controller.getParaNames());
			for (String string : aList) {
				params.put(string, controller.getPara(string));
			}
			boolean flag = checkSign(params, sign);
			if (!flag) {
				LogKit.warn("check sign error ");
				renderAuth(controller);
				return;
			}
			boolean verify = onVerify(params);
			if (!verify) {
				LogKit.warn("onVerify error ");
				renderAuth(controller);
				return;
			}
			inv.invoke();
			cache.setex(cacheKey, SIGN_INTERVAL, sign);
			return;
		} catch (Exception e) {
			LogKit.error("check sign error", e);
			renderAuth(controller);
		}

	}

	public static final String genSign(Controller controller) {
		Map<String, String> params = new HashMap<String, String>();
		ArrayList<String> aList = Collections.list(controller.getParaNames());
		for (String string : aList) {
			params.put(string, controller.getPara(string));
		}
		TreeMap<String, String> sortedParams = new TreeMap<String, String>(params);
		// 遍历排序后的字典，将所有参数按"key=value"格式拼接在一起
		StringBuilder sb = new StringBuilder();
		for (Entry<String, String> param : sortedParams.entrySet()) {
			String value = param.getValue();
			if (StrKit.isBlank(value)) {
				continue;
			}
			String key = param.getKey();
			if ("sign".equals(key)) {
				continue;
			}
			if ("token".equals(key)) {
				// 不校验token
				continue;
			}
			if ("str".equals(key)) {
				// str 是附加参数 用来debug
				continue;
			}
			// if ("version".equals(key)) {
			// // 不校验版本信息
			// continue;
			// }
			sb.append(key).append("=");
			sb.append(value);
			sb.append("&");
		}
		String string = sb.toString();
		String genSign = MD5Util.MD5Encode(string, "utf-8");
		return genSign;
	}

	public static final boolean checkSign(Map<String, String> params, String sign) {
		TreeMap<String, String> sortedParams = new TreeMap<String, String>(params);
		// 遍历排序后的字典，将所有参数按"key=value"格式拼接在一起
		StringBuilder sb = new StringBuilder();
		for (Entry<String, String> param : sortedParams.entrySet()) {
			String value = param.getValue();
			if (StrKit.isBlank(value)) {
				continue;
			}
			String key = param.getKey();
			if ("sign".equals(key)) {
				continue;
			}
			if ("token".equals(key)) {
				// 不校验token
				continue;
			}
			if ("str".equals(key)) {
				// str 是附加参数 用来debug
				continue;
			}
			// if ("version".equals(key)) {
			// // 不校验版本信息
			// continue;
			// }
			sb.append(key).append("=");
			sb.append(value);
			sb.append("&");
		}
		String string = sb.toString();
		String genSign = MD5Util.MD5Encode(string, "utf-8");
		boolean flag = sign.equals(genSign);
		System.out.println("[" + string + "]");
		System.out.println("[" + genSign + "]");
		return flag;
		// System.out.println("---------------------");
		// System.out.println(string);
		// System.out.println("-------*****---------");
		// System.out.println(getPara("str"));
		// System.out.println("-------*****---------");
		// System.out.println(sign);
		// System.out.println(getPara("sign"));
		// System.out.println("---------------------");
	}

}
